package leetcode.editor.cn;

//给定一个整数数组 arr，找到 min(b) 的总和，其中 b 的范围为 arr 的每个（连续）子数组。 
//
// 由于答案可能很大，因此 返回答案模 10^9 + 7 。 
//
// 
//
// 示例 1： 
//
// 
//输入：arr = [3,1,2,4]
//输出：17
//解释：
//子数组为 [3]，[1]，[2]，[4]，[3,1]，[1,2]，[2,4]，[3,1,2]，[1,2,4]，[3,1,2,4]。 
//最小值为 3，1，2，4，1，1，2，1，1，1，和为 17。 
//
// 示例 2： 
//
// 
//输入：arr = [11,81,94,43,3]
//输出：444
// 
//
// 
//
// 提示： 
//
// 
// 1 <= arr.length <= 3 * 10⁴ 
// 1 <= arr[i] <= 3 * 10⁴ 
// 
//
// 
//
// Related Topics 栈 数组 动态规划 单调栈 👍 544 👎 0

//Java：【907】 - 子数组的最小值之和
public class LeetCode_907_SumOfSubarrayMinimums{
    public static void main(String[] args) {
        Solution solution = new LeetCode_907_SumOfSubarrayMinimums().new Solution();
                // TO TEST
        System.out.println(solution.sumSubarrayMins(new int[]{3,1,2,4}));
        System.out.println(solution.sumSubarrayMins(new int[]{11,81,94,43,3}));
        System.out.println(solution.sumSubarrayMins(new int[]{71,55,82,55}));
    }
    
    //leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public int sumSubarrayMins(int[] arr) {
        int MOD = 1000000007;
        int n = arr.length;
        long ans = 0;
        for(int i=0;i<n;i++){
            ans = (ans+arr[i])%MOD;
            int left=0, right=0;
            while(i-left-1 >=0 && arr[i-left-1]>arr[i]) left++;
            while(i+right+1<n && arr[i+right+1]>=arr[i]) right++;
            ans = (ans + (long) arr[i] * left)%MOD; // i在子数组右边界
            ans = (ans + (long) arr[i] * right)%MOD; // i在子数组左边界
            ans = (ans + arr[i] * ((long) left * right)%MOD )%MOD; // i在子数组中间
        }
        return (int)ans;
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}
